<template>
  <div class="page">
    <div class="toolbar">
      <div class="toolbar-left">
        <a-input-search v-model:value="keyword" placeholder="输入关键字查询" allow-clear :enter-button="true"
          @search="onSearch" style="width: 40%" />
      </div>
      <div class="toolbar-right">
        <a-space>
          <a-button :disabled="!selectedRowKeys.length" danger @click="onBatchDelete">批量删除</a-button>
          <a-button :disabled="!selectedRowKeys.length" @click="onBatchDisable">批量停用</a-button>
          <a-button :disabled="!selectedRowKeys.length" @click="onBatchEnable">批量启用</a-button>
          <a-button type="primary" @click="onAdd">新增</a-button>
        </a-space>
      </div>
    </div>

    <!-- 列表卡片 -->
    <div class="content">
      <div class="table-wrap">
        <a-table :columns="columns" :data-source="pageData" :loading="loading" row-key="id" :pagination="false"
          :row-selection="rowSelection" size="middle" bordered class="table" :scroll="{ x: 'max-content' }"
          :customRow="onCustomRow">
          <template #bodyCell="{ column, record }">
            <template v-if="column.key === 'name'">
              <!-- 名称改为黑色纯文本，点击由整行承接 -->
              <span class="name-text">{{ record.name }}</span>
            </template>

            <template v-else-if="column.key === 'status'">
              <div class="status-cell">
                <span class="dot" :class="record.status === 'on' ? 'dot-on' : 'dot-off'"></span>
              </div>
            </template>

            <template v-else-if="column.key === 'actions'">
              <div class="actions">
                <a-typography-link @click="onEdit(record)">编辑</a-typography-link>
                <span class="sep">|</span>
                <a-typography-link @click="onDelete(record)" style="color: #ff4d4f">删除</a-typography-link>
                <span class="sep">|</span>
                <a-typography-link class="action-link" :aria-disabled="record.status === 'off'"
                  :class="{ disabled: record.status === 'off' }"
                  @click="record.status === 'on' && onDisable(record)">停用</a-typography-link>
                <span class="sep">|</span>
                <a-typography-link class="action-link" :aria-disabled="record.status === 'on'"
                  :class="{ disabled: record.status === 'on' }"
                  @click="record.status === 'off' && onEnable(record)">启用</a-typography-link>
              </div>
            </template>
          </template>
        </a-table>
      </div>

      <!-- 底部分页 -->
      <div class="viewport-sticky-footer">
        <div class="footer-left">
          <a-checkbox :checked="checkAll" :indeterminate="indeterminate" @change="onToggleAll">全选</a-checkbox>
          <span class="sel">已选 {{ selectedRowKeys.length }} 项</span>
        </div>

        <div class="footer-right">
          <span class="stat">本页 {{ pageData.length }} 条，共 {{ total }} 条</span>
          <a-pagination v-model:current="page" v-model:pageSize="pageSize" :total="total" :show-size-changer="true"
            :page-size-options="['10', '20', '50', '100']" show-quick-jumper @change="onPageChange"
            @showSizeChange="onPageSizeChange" />
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { computed, onMounted, ref } from "vue";
import { message, Modal } from "ant-design-vue";
import { useRouter } from "vue-router";
import {
  listDefaultKeywords,
  enableDefaultKeyword,
  disableDefaultKeyword,
  updateDefaultKeyword,
  updateDefaultKeywords,
  type DefaultKeywordItem,
  fetchVerticalCategoryOptions,
} from "@/api/modules/default-search-keyword";

type RowStatus = "on" | "off";
interface RowItem {
  id: number | string;
  name: string;
  channel: string;
  status: RowStatus;
  onlineAt: string;
}

const router = useRouter();

const channelDict = ref<Record<string, string>>({});
async function loadChannelDict() {
  try {
    const rows = await fetchVerticalCategoryOptions({ page: 1, pageSize: -1 });
    const map: Record<string, string> = {};
    (rows || []).forEach((it: any) => {
      const key = it?.value != null ? String(it.value).trim() : "";
      const label = it?.query ?? "";
      if (key) map[key] = label || key;
    });
    channelDict.value = map;
  } catch (e: any) {
    console.warn("loadChannelDict failed:", e?.message || e);
  }
}

const columns: any[] = [
  { title: "名称", dataIndex: "name", key: "name", ellipsis: true, width: 120 },
  { title: "应用频道", dataIndex: "channel", key: "channel", width: 120 },
  { title: "状态", dataIndex: "status", key: "status", width: 100, align: "center" },
  { title: "上线时间", dataIndex: "onlineAt", key: "onlineAt", width: 200 },
  { title: "操作", key: "actions", width: 160, fixed: "right" },
];

const loading = ref(false);
const keyword = ref("");
const pageData = ref<RowItem[]>([]);
const page = ref(1);
const pageSize = ref(10);
const total = ref(0);
const selectedRowKeys = ref<Array<number | string>>([]);

const checkAll = computed(
  () => pageData.value.length > 0 && pageData.value.every((r) => selectedRowKeys.value.includes(r.id))
);
const indeterminate = computed(() => {
  const sel = selectedRowKeys.value.filter((k) => pageData.value.some((r) => r.id === k)).length;
  return sel > 0 && sel < pageData.value.length;
});
const rowSelection = computed(() => ({
  selectedRowKeys: selectedRowKeys.value,
  onChange: (keys: (string | number)[]) => (selectedRowKeys.value = keys as Array<number | string>),
}));

function formatDate(s?: string) { return s ? s.replace("T", " ").slice(0, 19) : "-"; }
function toRow(it: DefaultKeywordItem): RowItem {
  const raw = (it as any).sence ? String((it as any).sence).trim() : "";
  const mapped = raw ? (channelDict.value[raw] ?? raw) : "-";
  return {
    id: it.id!,
    name: it.query ?? "-",
    channel: mapped,
    status: it.status === "published" ? "on" : "off",
    onlineAt: formatDate((it as any).date_updated || (it as any).date_created),
  };
}
function totalPages() { return Math.max(1, Math.ceil(total.value / pageSize.value)); }

async function fetchList() {
  loading.value = true;
  try {
    const { list, total: t } = await listDefaultKeywords({
      page: page.value,
      pageSize: pageSize.value,
      keyword: keyword.value.trim(),
      sort: "-id",
    });
    total.value = t;

    const max = totalPages();
    if (page.value > max) {
      page.value = max;
      const again = await listDefaultKeywords({
        page: page.value,
        pageSize: pageSize.value,
        keyword: keyword.value.trim(),
        sort: "-id",
      });
      pageData.value = again.list.map(toRow);
      total.value = again.total;
    } else {
      pageData.value = list.map(toRow);
    }

    const idsNow = new Set(pageData.value.map((x) => String(x.id)));
    selectedRowKeys.value = selectedRowKeys.value.filter((k) => idsNow.has(String(k)));
  } catch (e: any) {
    message.error(e?.message || "获取数据失败");
  } finally {
    loading.value = false;
  }
}

/* 整行跳转（操作列与选择列除外） */
function onCustomRow(record: RowItem) {
  return {
    onClick: (e: MouseEvent) => {
      const el = e.target as HTMLElement;
      if (
        el.closest(".actions") ||                // 操作区域
        el.closest(".ant-btn") ||                // 任意按钮
        el.closest(".ant-checkbox-wrapper") ||   // 选择列
        el.closest(".ant-checkbox") ||
        el.tagName.toLowerCase() === "a"         // 内部可能的链接
      ) {
        return;
      }
      goInfo(record);
    },
    style: { cursor: "pointer" },
  } as any;
}

/* 跳转 */
function goInfo(row: RowItem) { router.push({ name: "defaultSearchTermInfo", query: { id: String(row.id) } }); }
function onAdd() { router.push({ name: "defaultSearchTermPage" }); }
function onEdit(row: RowItem) { router.push({ name: "defaultSearchTermPage", query: { id: String(row.id) } }); }

/* 启/停/删除/批量 */
async function onEnable(row: RowItem) {
  try { loading.value = true; await enableDefaultKeyword(row.id); message.success("已启用"); await fetchList(); }
  catch (e: any) { message.error(e?.message || "启用失败"); }
  finally { loading.value = false; }
}
async function onDisable(row: RowItem) {
  try { loading.value = true; await disableDefaultKeyword(row.id); message.success("已停用"); await fetchList(); }
  catch (e: any) { message.error(e?.message || "停用失败"); }
  finally { loading.value = false; }
}
async function onBatchEnable() {
  if (!selectedRowKeys.value.length) return;
  try {
    loading.value = true;
    await updateDefaultKeywords(selectedRowKeys.value.map((id) => ({ id, status: "published" as const })));
    selectedRowKeys.value = [];
    message.success("批量启用完成");
    await fetchList();
  } catch (e: any) {
    message.error(e?.message || "批量启用失败");
  } finally {
    loading.value = false;
  }
}
async function onBatchDisable() {
  if (!selectedRowKeys.value.length) return;
  try {
    loading.value = true;
    await updateDefaultKeywords(selectedRowKeys.value.map((id) => ({ id, status: "draft" as const })));
    selectedRowKeys.value = [];
    message.success("批量停用完成");
    await fetchList();
  } catch (e: any) {
    message.error(e?.message || "批量停用失败");
  } finally {
    loading.value = false;
  }
}

async function refetchAndFixPage() { await fetchList(); }

function onDelete(row: RowItem) {
  Modal.confirm({
    title: "确认删除？",
    content: `确定删除「${row.name}」吗？`,
    onOk: async () => {
      try {
        loading.value = true;
        await updateDefaultKeyword(row.id, { status: "archived" });
        message.success("删除成功");
        await refetchAndFixPage();
      } catch (e: any) {
        message.error(e?.message || "删除失败");
      } finally {
        loading.value = false;
      }
    },
  });
}
function onBatchDelete() {
  Modal.confirm({
    title: "批量删除",
    content: `确定删除选中的 ${selectedRowKeys.value.length} 项吗？`,
    onOk: async () => {
      if (!selectedRowKeys.value.length) return;
      try {
        loading.value = true;
        await updateDefaultKeywords(selectedRowKeys.value.map((id) => ({ id, status: "archived" as const })));
        selectedRowKeys.value = [];
        message.success("已删除");
        await refetchAndFixPage();
      } catch (e: any) {
        message.error(e?.message || "批量删除失败");
      } finally {
        loading.value = false;
      }
    },
  });
}

/* 选择/搜索/分页 */
function onToggleAll(e: any) {
  const ids = pageData.value.map((r) => r.id);
  selectedRowKeys.value = e.target.checked
    ? Array.from(new Set([...selectedRowKeys.value, ...ids]))
    : selectedRowKeys.value.filter((k) => !ids.includes(k));
}
function onSearch() { page.value = 1; fetchList(); }

/** 分页事件 */
function onPageChange(nextPage: number, nextPageSize: number) {
  page.value = nextPage;
  if (nextPageSize && nextPageSize !== pageSize.value) pageSize.value = nextPageSize;
  fetchList();
}
function onPageSizeChange(_current: number, size: number) {
  pageSize.value = size;
  page.value = 1;
  fetchList();
}

/** 先加载频道字典，再拉列表 */
onMounted(async () => {
  await loadChannelDict();
  await fetchList();
});
</script>

<style scoped>
/* ======= 变量 ======= */
:root {
  --card-radius: 12px;
  --card-border: #f0f0f0;
  --page-bg: #f5f6f8;
}

/* 表格与分页器的固定关系 */
.page {
  --footer-gap: 20px;
  --footer-h: 120px;
}

.page {
  width: 100%;
  height: 100dvh;
  min-height: 100vh;
  overflow: hidden;
  background: var(--page-bg);
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* 顶部工具条 */
.toolbar {
  background: #fff;
  border: 1px solid var(--card-border);
  border-radius: var(--card-radius);
  padding: 12px 16px;
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.toolbar-left {
  flex: 1;
  min-width: 220px;
}

/* 内容卡片 */
.content {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: #fff;
  border: 1px solid var(--card-border);
  border-radius: var(--card-radius);
  padding: 12px 16px;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-y: contain;
  scrollbar-gutter: stable;
}

/* 表格外层：负责横向滚动 */
.table-wrap {
  flex: 1 1 auto;
  min-height: 0;
  overflow-x: auto;
  overflow-y: visible;
}

.table {
  width: 100%;
}

.table :deep(.ant-table) {
  width: 100%;
}

.table :deep(.ant-table-container) {
  width: 100%;
}

.table :deep(table) {
  table-layout: auto;
  width: max-content;
  min-width: 100%;
}

/* ——去掉右侧“滚动条占位列/空白带”—— */
.table :deep(.ant-table-cell-scrollbar),
.table :deep(.ant-table-thead > tr > .ant-table-cell-scrollbar),
.table :deep(.ant-table-tbody > tr > .ant-table-cell-scrollbar) {
  display: none !important;
  width: 0 !important;
  min-width: 0 !important;
  padding: 0 !important;
  border: 0 !important;
}

.table :deep(.ant-table-header) {
  margin-right: 0 !important;
}


.table :deep(tr.ant-table-measure-row) {
  height: 0 !important;
  line-height: 0 !important;
  font-size: 0 !important;
  border: 0 !important;
}

.table :deep(tr.ant-table-measure-row > td) {
  padding: 0 !important;
  border: 0 !important;
  height: 0 !important;
  line-height: 0 !important;
}

/* ——正文行固定 */
.table :deep(.ant-table-tbody > tr:not(.ant-table-measure-row) > td) {
  height: 40px !important;
  line-height: 40px !important;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
}

/* 表头样式 */
.table :deep(.ant-table-thead > tr > th) {
  background: #f4f8fd !important;
  white-space: nowrap;
}

/* 名称 */
.table :deep(.name-text) {
  color: #000;
}

/* 底部分页 */
.viewport-sticky-footer {
  flex: 0 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: var(--footer-gap);
  padding-top: 8px;
  border-top: 1px solid var(--card-border);
  min-height: var(--footer-h);
  background: #fff;
}

.viewport-sticky-footer :deep(.ant-pagination) {
  margin: 0;
}

.footer-left,
.footer-right {
  display: flex;
  align-items: center;
  gap: 12px;
}

.sel,
.stat {
  color: #8c8c8c;
}

/* 状态点 */
.status-cell {
  display: flex;
  align-items: center;
  justify-content: center;
}

.dot {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  display: inline-block;
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2), 0 1px 1px rgba(0, 0, 0, .08);
}

.dot-on {
  background: radial-gradient(60% 60% at 35% 35%, #b9ffe0 0%, #41e0a0 55%, #16b679 100%);
}

.dot-off {
  background: radial-gradient(60% 60% at 35% 35%, #ffb6be 0%, #ff5a5f 55%, #d9363e 100%);
}

/* 操作列 */
.actions {
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.sep {
  color: #d9d9d9;
}

.action-link.disabled {
  color: #bfbfbf !important;
  pointer-events: none;
  cursor: not-allowed;
}

/* 字体微调 */
@media (max-width: 991px) {

  .table :deep(.ant-table-thead > tr > th),
  .table :deep(.ant-table-tbody > tr > td) {
    font-size: 13px;
  }
}

@media (max-width: 767px) {

  .table :deep(.ant-table-thead > tr > th),
  .table :deep(.ant-table-tbody > tr > td) {
    font-size: 12px;
  }

  .page {
    --footer-h: 56px;
  }

  .toolbar {
    padding: 10px 12px;
  }

  .page {
    padding: 8px;
    gap: 8px;
  }
}
</style>
